package com.wwu.common.utils;

import org.springframework.core.convert.converter.Converter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

/**
 *  日期工具类
 * @author 一蓑烟雨
 * @date 2021-10-26 15:49
 * @version 1.0.0
 **/
public class DateUtils implements Converter<String, LocalDate> {

    /**
     * 日期字符串转换为日期格式，返回格式yyyy-MM-dd
     * @param source 日期字符串
     * @return java.time.LocalDate
     * @author 一蓑烟雨
     * @date 2021/12/9 0009 上午 9:45
     */
    @Override
    public LocalDate convert(String source) {
        return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    /**
     * 日期时间格式转换为年份字符串,返回格式yyyy-MM
     * @param date 日期格式
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:07
     */
    public static String convertYearToStr(Date date) {
        DateFormat df = new SimpleDateFormat("yyyy");
        return df.format(date);
    }

    /**
     * 日期时间格式转换为年月字符串,返回格式yyyy-MM
     * @param date 日期格式
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:06
     */
    public static String convertYearMonthToStr(Date date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM");
        return df.format(date);
    }

    /**
     * 日期格式转换为日期字符串,返回格式yyyyMMdd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:58
     */
    public static String convertDateToStr() {
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        return df.format(new Date());
    }

    /**
     * 日期格式转换为日期字符串,返回格式yyyy-MM-dd
     * @param date 日期格式
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:50
     */
    public static String convertDateToStrUk(Date date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(date);
    }

    /**
     * 日期时间格式转换为日期时间字符串,返回格式yyyyMMddHHmmss
     * @param date 日期格式
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:56
     */
    public static String convertDateTimeToStr(Date date) {
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        return df.format(date);
    }

    /**
     * 日期时间格式转换为日期时间字符串,返回格式yyyy-MM-dd HH:mm:ss
     * @param date 日期格式
     * @return null
     * @author 一蓑烟雨
     * @date 2023/5/31 21:50
     */
    public static String convertDateTimeToStrUk(Date date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(date);
    }


    /**
     * 日期时间字符串转换为日期时间格式,返回格式yyyy-MM-dd HH:mm:ss
     * @param date 格式yyyy-MM-dd HH:mm:ss
     * @return java.util.Date
     * @author 一蓑烟雨
     * @date 2023/5/31 21:51
     */
    public static Date convertStrToDateTimeUk(String date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return df.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 日期字符串转换为日期格式,返回格式yyyy-MM-dd
     * @param date 格式yyyy-MM-dd
     * @return java.util.Date
     * @author 一蓑烟雨
     * @date 2023/5/31 22:01
     */
    public static Date convertStrToDateUk(String date) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return df.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获取当前年份，返回格式yyyy
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:04
     */
    public static String getCurrentYear() {
        DateFormat df = new SimpleDateFormat("yyyy");
        return df.format(new Date());
    }

    /**
     * 获取当前年月，返回格式yyyy-MM
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:02
     */
    public static String getCurrentYearMonth() {
        DateFormat df = new SimpleDateFormat("yyyy-MM");
        return df.format(new Date());
    }

    /**
     * 获取当前日期，返回格式yyyy-MM-dd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:46
     */
    public static String getCurrentDateUk() {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(new Date());
    }

    /**
     * 获取当前日期时间，返回格式yyyyMMddHHmmss
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:54
     */
    public static String getCurrentDateTime() {
        DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        return df.format(new Date());
    }

    /**
     * 获取当前日期时间，返回格式yyyy-MM-dd HH:mm:ss
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:44
     */
    public static String getCurrentDateTimeUk() {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(new Date());
    }

    /**
     * 获取当前日期时间，返回格式yyyy年MM月dd日 HH时mm分ss秒
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 21:53
     */
    public static String getCurrentDateTimeZh() {
        DateFormat df = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        return df.format(new Date());
    }


    /**
     * 获取当前月天数
     * @return int
     * @author 一蓑烟雨
     * @date 2023/5/31 22:08
     */
    public static int getCurrentMonthDayNum() {
        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
        return aCalendar.getActualMaximum(Calendar.DATE);

    }

    /**
     * 获取当前月最后一天，返回格式yyyy-MM-dd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:09
     */
    public static String getCurrentMonthLastDay() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(new Date());
        calendar2.set(Calendar.DAY_OF_MONTH, calendar2.getActualMaximum(Calendar.DAY_OF_MONTH));
        return sdf.format(calendar2.getTime());
    }

    /**
     * 获取指定月份的最后一天，返回格式yyyy-MM-dd
     * @param month  参数格式yyyy-MM
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:10
     */
    public static String getMonthLastDay(String month) {
        try {
            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM");
            SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(sdf1.parse(month));
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            return sdf2.format(calendar.getTime());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取指定日期往后或往前多少天的日期，返回格式yyyy-MM-dd
     * @param date 格式yyyy-MM-dd
     * @param days 小于0则往前推，大于0则往后推
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:11
     */
    public static String getDateDiff(Date date, int days) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, days);
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取指定日期往后或往前多少天的日期，返回格式yyyy-MM-dd
     * @param date 格式yyyy-MM-dd
     * @param days 小于0则往前推，大于0则往后推
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:15
     */
    public static String getStrDateDiff(String date, int days) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = new GregorianCalendar();
        try {
            calendar.setTime(sdf.parse(date));
            // 把日期往后增加一天.整数往后推,负数往前移动
            calendar.add(calendar.DATE, days);
            return sdf.format(calendar.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取本周周一对应的日期，返回格式yyyy-MM-dd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:15
     */
    public static String getCurrentWeekMonday() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        String imptimeBegin = sdf.format(cal.getTime());
        cal.add(Calendar.DATE, 6);
        return imptimeBegin;
    }

    /**
     * 获取本周周日对应的日期，返回格式yyyy-MM-dd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:16
     */
    public static String getCurrentWeekSundayYmd() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        // 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        cal.add(Calendar.DATE, 6);
        return sdf.format(cal.getTime());
    }

    /**
     * 补全开始时间,返回格式yyyy-MM-dd 00:00:00
     * @param date   格式yyyy-MM-dd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:17
     */
    public static String completeTimeStart(String date) {
        return date + " 00:00:00";
    }

    /**
     * 补全结束时间,返回格式yyyy-MM-dd 23:59:59
     * @param date   格式yyyy-MM-dd
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:17
     */
    public static String completeTimeEnd(String date) {
        return date + " 23:59:59";
    }

    /**
     * 获取两个时间的时间差，返回格式xx天xx时xx分
     * @param endDate 开始时间
     * @param nowDate 结束时间
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:19
     */
    public static String getDateTimeDiffer(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = Math.abs(endDate.getTime() - nowDate.getTime());
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        return day + "天" + hour + "时" + min + "分";
    }

    /**
     * 获得两个时间差多少小时
     * @param startDate 开始时间
     * @param nowDate 结束时间
     * @return long
     * @author 一蓑烟雨
     * @date 2023/5/31 22:21
     */
    public static long getDateDiffHour(Date startDate, Date nowDate) {
        long nh = 1000 * 60 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = nowDate.getTime() - startDate.getTime();
        // 相差多少小时
        return diff / nh;
    }

    /**
     * 根据出生日期算年龄
     * @param birthday 日期格式
     * @return int
     * @author 一蓑烟雨
     * @date 2023/5/31 22:19
     */
    private static int getAgeByBirthDay(Date birthday) {
        int age = 0;
        try {
            Calendar now = Calendar.getInstance();
            now.setTime(new Date());
            Calendar birth = Calendar.getInstance();
            birth.setTime(birthday);
            // 如果传入的时间，在当前时间的后面，返回0岁
            if (birth.after(now)) {
                age = 0;
            } else {
                age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
                if (now.get(Calendar.DAY_OF_YEAR) > birth.get(Calendar.DAY_OF_YEAR)) {
                    age += 1;
                }
            }
            return age;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return age;
    }

    /**
     * 获取n年后今天的日期，返回格式yyyy-MM-dd
     * @param num n年
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:23
     */
    public static String getAfterYearDateYmd(int num) {
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        // 设置起时间
        cal.setTime(date);
        // 增加一年
        cal.add(Calendar.YEAR, num);
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(cal.getTime());
    }

    /**
     * 获取指定月份的下个月的今天，返回格式yyyy-MM-dd
     * @param date 格式yyyy-MM-dd
     * @param i 下个月
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:22
     */
    public static String getNextMonthDayYmd(String date, int i) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date resDate = convertStrToDateUk(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(resDate);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + i);
        resDate = calendar.getTime();
        return dateFormat.format(resDate);
    }

    /**
     * 获取指定月份的上个月的今天，返回格式yyyy-MM-dd
     * @param date 格式yyyy-MM-dd
     * @param i 上个月
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:22
     */
    public static String getLastMonthDay(String date, int i) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date resDate = convertStrToDateUk(date);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(resDate);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - i);
        resDate = calendar.getTime();
        return dateFormat.format(resDate);
    }

    /**
     * 获取指定月份的上个月，返回格式yyyy-MM
     * @param month 指定月份，格式yyyy-MM
     * @return java.lang.String
     * @author 一蓑烟雨
     * @date 2023/5/31 22:21
     */
    public static String getLastMonth(String month) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar calendar = Calendar.getInstance();
        try {
            Date date = sdf.parse(month);
            calendar.setTime(date);
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
            date = calendar.getTime();
            return sdf.format(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}
